﻿/*----------------------------------------------------------------
// Copyright (C) 2014 苏州麦迪斯顿医疗科技股份有限公司
// 文件名：DynamicChannelFactory.cs
// 文件功能描述：DynamicChannelFactory
// 创建标识：顾伟伟-2014-04-03
----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

using System.Diagnostics;

namespace CPOE.Framework.Throttling
{
    /// <summary>
    /// 一个自定义的ChannelFactory，用于随机动态分配服务终结点地址，实现服务分流
    /// </summary>
    /// <typeparam name="TChannel"></typeparam>
    public class DynamicChannelFactory<TChannel> : ChannelFactory<TChannel>
    {
        public DynamicChannelFactory(string endpointName)
            : base(endpointName)
        {

        }
        /// <summary>
        /// 在服务器IP列表中随机选择一个可用的IP创建WCF通道，如果没有可用的IP，则抛出InvalidOperationException
        /// </summary>
        /// <param name="address"></param>
        /// <param name="via"></param>
        /// <returns></returns>
        public override TChannel CreateChannel(EndpointAddress address, Uri via)
        {
            var uri = address.Uri.OriginalString;
            var count = NetworkAddressTable.Count;

            TChannel channel =default(TChannel);

            for (int i = 0; i < count; i++)
            {
                //从地址表中随机获取一个终结点地址
                address = new EndpointAddress(NetworkAddressTable.GetRandomAddress(uri));
                //创建传输通道
                var transport = base.CreateChannel(address, via);
                var comminication = transport as ICommunicationObject;
                try
                {
                    //显式打开通道
                    comminication.Open();
                    channel = transport;
                    break;
                }
                catch (Exception e)
                {
                    //强制关闭通道
                    comminication.Abort();
                    //从IP表中移去脱机服务器IP
                    NetworkAddressTable.SetServerNotAlive(address.Uri.DnsSafeHost);
                    Trace.TraceWarning(string.Format("IP为:{0}的服务器连接失败,{1}", address.Uri.DnsSafeHost, e.Message));
                    //重新选择服务终结点
                    continue;
                }

            }
            if (channel == null )
                throw new InvalidOperationException("无法创建到服务器的传输通道,请检查网络设置");

            return channel;
            
        }
    }
}
